﻿using FySystem.Extension;
using FySystem.Logs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IOT.Services
{
    public class DeviceService<T>
    {
        private int _timer = 0;

        /// <summary>
        /// 存放所有的连接，key一般为设备序列号
        /// </summary>
        internal Dictionary<string, IOTStateObject<T>> CLIENTS = new Dictionary<string, IOTStateObject<T>>();

        /// <summary>
        /// 添加设备
        /// </summary>
        /// <param name="key"></param>
        /// <param name="state"></param>
        /// <exception cref="NotImplementedException"></exception>
        public void AddDevice(string key, IOTStateObject<T> state)
        {
            try
            {
                lock (CLIENTS)
                {
                    if (CLIENTS.ContainsKey(key))
                        CLIENTS[key] = state;
                    else
                        CLIENTS.Add(key, state);
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 获取所有设备连接
        /// </summary>
        /// <returns></returns>
        public IOTStateObject<T>[] GetAllDevices()
        {
            IOTStateObject<T>[] res = null;
            try
            {
                lock (CLIENTS)
                {
                    res = CLIENTS.Values.ToArray();
                }
            }
            catch (Exception)
            {
                throw;
            }
            return res;
        }

        /// <summary>
        /// 查找链接
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public IOTStateObject<T> FindDevice(string key)
        {
            IOTStateObject<T> res = null;
            try
            {
                lock (CLIENTS)
                {
                    CLIENTS.TryGetValue(key, out res);
                }
            }
            catch (Exception)
            {
                throw;
            }
            return res;
        }

        /// <summary>
        /// 连接实际靠这个来发送数据
        /// </summary>
        /// <param name="iotFactory"></param>
        /// <exception cref="NotImplementedException"></exception>
        internal void RealSend(IOTLCFactory<T> iotFactory)
        {
            try
            {
                var clients = GetAllDevices();
                if (clients.IsNullOrEmpty())
                    return;

                foreach (var item in clients)
                {
                    item.Send(iotFactory.TimeOut,iotFactory.SendDeltaTime);
                }
            }
            catch (Exception ex)
            {
                FyLogContextV2.WriteError("DeviceService.RealSend", ex.Message);
            }
        }

        /// <summary>
        /// 无效连接回收
        /// </summary>
        /// <param name="iOTService"></param>
        /// <exception cref="NotImplementedException"></exception>
        internal void GC(IOTLCFactory<T> iOTFactory)
        {
            try
            {
                _timer++;
                if (_timer >= 6000)
                {
                    _timer = 0;

                    List<string> invalidates = new List<string>();
                    DateTime now = DateTime.Now;

                    lock (CLIENTS)
                    {
                        foreach (string key in CLIENTS.Keys)
                        {
                            var client = CLIENTS[key];
                            if ((now - client.LastReceivedTime).TotalMinutes >= 15 || client.WorkSocket.Connected == false)
                            {
                                //15分钟一直没收到数据认为是离线
                                invalidates.Add(key);
                            }
                        }

                        foreach(var key in invalidates)
                        {
                            CLIENTS.Remove(key);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                FyLogContextV2.WriteError("DeviceService.GC", ex.Message);
            }
        }
    }
}
